package com.shrct.businessprocess.product.impl;

import com.google.common.collect.Iterables;
import com.shrct.businessprocess.organization.RCEnterprise;
import com.shrct.businessprocess.product.RCFullService;
import com.shrct.businessprocess.product.RCFullServiceProductEntry;
import com.shrct.businessprocess.product.RCIdentifiablePhysicalProductEntry;
import com.shrct.businessprocess.product.RCIdentifiablePhysicalProductEntryStatus;
import com.shrct.businessprocess.product.RCLogicProduct;
import com.shrct.businessprocess.product.RCLogicProductEvent;
import com.shrct.businessprocess.product.RCProductEvent;
import com.shrct.businessprocess.product.RCProductMetaType;
import com.shrct.businessprocess.product.RCProductSpecification;
import com.shrct.businessprocess.product.impl.RCIdentifiableProductEntryImpl;
import com.shrct.businessprocess.product.impl.RCLogicProductImpl;
import com.shrct.businessprocess.product.proxy.RCIdentifiablePhysicalProductEntryProxy;
import com.shrct.businessprocess.purchase.RCPurchaseOrderItem;
import edu.fudan.langlab.domain.statemachine.ModelObjectLogService;
import edu.fudan.mylang.pf.IGenericQuery;
import edu.fudan.mylang.pf.IObjectFactory;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;

@Entity
@DiscriminatorValue("RCIDENTIFIABLEPHYSICALPRODUCTENTRY_TYPE")
public class RCIdentifiablePhysicalProductEntryImpl extends RCIdentifiableProductEntryImpl implements RCIdentifiablePhysicalProductEntry {
  public RCIdentifiablePhysicalProductEntryImpl() {
    super();
  }
  
  private RCIdentifiablePhysicalProductEntryStatus Status;
  
  public RCIdentifiablePhysicalProductEntryStatus getStatus() {
    return this.Status;
  }
  
  private ModelObjectLogService getModelObjectLogService() {
    return getBeanFactory().getBean(ModelObjectLogService.class);
  }
  
  private void _start() {
    
    Status=RCIdentifiablePhysicalProductEntryStatus.Created;
  }
  
  public void start() {
    if(Status==null){
    	_start();
    	getModelObjectLogService().createLog(this,"Status","Start");
    	getBeanFactory().getBean(com.shrct.businessprocess.product.events.RCIdentifiablePhysicalProductEntryEventsManager.class).fireStarted(this);					
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException("allready started");
    }
  }
  
  private void __inStock(final RCPurchaseOrderItem orderItem) {
    
    Status=RCIdentifiablePhysicalProductEntryStatus.InStocking;
  }
  
  public void _inStock(final RCPurchaseOrderItem orderItem) {
    if(Status==RCIdentifiablePhysicalProductEntryStatus.Created){
    	__inStock(orderItem);
    	getModelObjectLogService().createLog(this,"Status","_inStock");
    	getBeanFactory().getBean(com.shrct.businessprocess.product.events.RCIdentifiablePhysicalProductEntryEventsManager.class).fire_inStock(this,orderItem);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void __import() {
    
    Status=RCIdentifiablePhysicalProductEntryStatus.Imported;
  }
  
  public void _import() {
    if(Status==RCIdentifiablePhysicalProductEntryStatus.Created){
    	__import();
    	getModelObjectLogService().createLog(this,"Status","_import");
    	getBeanFactory().getBean(com.shrct.businessprocess.product.events.RCIdentifiablePhysicalProductEntryEventsManager.class).fire_import(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void __rmaImport() {
    
    Status=RCIdentifiablePhysicalProductEntryStatus.RMAImported;
  }
  
  public void _rmaImport() {
    if(Status==RCIdentifiablePhysicalProductEntryStatus.Created){
    	__rmaImport();
    	getModelObjectLogService().createLog(this,"Status","_rmaImport");
    	getBeanFactory().getBean(com.shrct.businessprocess.product.events.RCIdentifiablePhysicalProductEntryEventsManager.class).fire_rmaImport(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void __deliver(final RCEnterprise enterprise) {
    
    Status=RCIdentifiablePhysicalProductEntryStatus.Delivered;
  }
  
  public void _deliver(final RCEnterprise enterprise) {
    if(Status==RCIdentifiablePhysicalProductEntryStatus.InStocking){
    	__deliver(enterprise);
    	getModelObjectLogService().createLog(this,"Status","_deliver");
    	getBeanFactory().getBean(com.shrct.businessprocess.product.events.RCIdentifiablePhysicalProductEntryEventsManager.class).fire_deliver(this,enterprise);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void __cancelInStock() {
    
  }
  
  public void _cancelInStock() {
    if(Status==RCIdentifiablePhysicalProductEntryStatus.InStocking){
    	__cancelInStock();
    	getModelObjectLogService().createLog(this,"Status","_cancelInStock");
    	getBeanFactory().getBean(com.shrct.businessprocess.product.events.RCIdentifiablePhysicalProductEntryEventsManager.class).fire_cancelInStock(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void __return() {
    
    Status=RCIdentifiablePhysicalProductEntryStatus.InStocking;
  }
  
  public void _return() {
    if(Status==RCIdentifiablePhysicalProductEntryStatus.Delivered){
    	__return();
    	getModelObjectLogService().createLog(this,"Status","_return");
    	getBeanFactory().getBean(com.shrct.businessprocess.product.events.RCIdentifiablePhysicalProductEntryEventsManager.class).fire_return(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void __rmaReplace() {
    
    Status=RCIdentifiablePhysicalProductEntryStatus.RMAReplaced;
  }
  
  public void _rmaReplace() {
    if(Status==RCIdentifiablePhysicalProductEntryStatus.Imported||Status==RCIdentifiablePhysicalProductEntryStatus.Delivered||Status==RCIdentifiablePhysicalProductEntryStatus.RMAImported){
    	__rmaReplace();
    	getModelObjectLogService().createLog(this,"Status","_rmaReplace");
    	getBeanFactory().getBean(com.shrct.businessprocess.product.events.RCIdentifiablePhysicalProductEntryEventsManager.class).fire_rmaReplace(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  public Boolean isCreated() {
    return com.shrct.businessprocess.product.RCIdentifiablePhysicalProductEntryStatus.Created==Status;
  }
  
  public Boolean isInStocking() {
    return com.shrct.businessprocess.product.RCIdentifiablePhysicalProductEntryStatus.InStocking==Status;
  }
  
  public Boolean isDelivered() {
    return com.shrct.businessprocess.product.RCIdentifiablePhysicalProductEntryStatus.Delivered==Status;
  }
  
  public Boolean isImported() {
    return com.shrct.businessprocess.product.RCIdentifiablePhysicalProductEntryStatus.Imported==Status;
  }
  
  public Boolean isRMAImported() {
    return com.shrct.businessprocess.product.RCIdentifiablePhysicalProductEntryStatus.RMAImported==Status;
  }
  
  public Boolean isRMAReplaced() {
    return com.shrct.businessprocess.product.RCIdentifiablePhysicalProductEntryStatus.RMAReplaced==Status;
  }
  
  @JoinColumn(name = "logicProduct_id")
  @ManyToOne(targetEntity = RCLogicProductImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCLogicProduct logicProduct;
  
  public RCLogicProduct getLogicProduct() {
    return this.logicProduct;
  }
  
  public RCIdentifiablePhysicalProductEntry setLogicProduct(final RCLogicProduct logicProduct) {
    this.logicProduct = logicProduct;
    return this;			
    
  }
  
  private Boolean isReplaced = Boolean.valueOf(false);
  
  public Boolean getIsReplaced() {
    return this.isReplaced;
  }
  
  public RCIdentifiablePhysicalProductEntry setIsReplaced(final Boolean isReplaced) {
    this.isReplaced = isReplaced;
    return this;			
    
  }
  
  private Boolean isBorrowReplaced = Boolean.valueOf(false);
  
  public Boolean getIsBorrowReplaced() {
    return this.isBorrowReplaced;
  }
  
  public RCIdentifiablePhysicalProductEntry setIsBorrowReplaced(final Boolean isBorrowReplaced) {
    this.isBorrowReplaced = isBorrowReplaced;
    return this;			
    
  }
  
  @JoinColumn(name = "parent_id")
  @ManyToOne(targetEntity = RCIdentifiablePhysicalProductEntryImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCIdentifiablePhysicalProductEntry parent;
  
  public RCIdentifiablePhysicalProductEntry getParent() {
    return this.parent;
  }
  
  public RCIdentifiablePhysicalProductEntry setParent(final RCIdentifiablePhysicalProductEntry parent) {
    this.parent = parent;
    return this;			
    
  }
  
  public Iterable<RCIdentifiablePhysicalProductEntry> allParts() {
    IGenericQuery<RCIdentifiablePhysicalProductEntry> query=getObjectFactory().createGenericQuery(RCIdentifiablePhysicalProductEntry.class,"select e from com.shrct.businessprocess.product.impl.RCIdentifiablePhysicalProductEntryImpl as e   where ((e.parent) = (:this)) and  e.active = 1      ").setParameter("this",this);
    Collection<RCIdentifiablePhysicalProductEntry> _list = query.list();
    return _list;
  }
  
  public Iterable<RCFullServiceProductEntry> getServices() {
    Collection<RCFullService> _fullServices = this.logicProduct.getFullServices();
    final Function1<RCFullService,Collection<RCFullServiceProductEntry>> _function = new Function1<RCFullService,Collection<RCFullServiceProductEntry>>() {
        public Collection<RCFullServiceProductEntry> apply(final RCFullService it) {
          Collection<RCFullServiceProductEntry> _entries = it.getEntries();
          return _entries;
        }
      };
    Iterable<Collection<RCFullServiceProductEntry>> _map = IterableExtensions.<RCFullService, Collection<RCFullServiceProductEntry>>map(_fullServices, _function);
    Iterable<RCFullServiceProductEntry> _flatten = Iterables.<RCFullServiceProductEntry>concat(_map);
    return _flatten;
  }
  
  public Collection<? extends RCProductEvent> getEvents() {
    Collection<RCLogicProductEvent> _events = this.logicProduct.getEvents();
    return _events;
  }
  
  public RCProductMetaType getProductMetaType() {
    RCProductSpecification _type = this.getType();
    RCProductMetaType _productMetaType = _type.getProductMetaType();
    return _productMetaType;
  }
  
  public static RCIdentifiablePhysicalProductEntry create(final IObjectFactory objectFactory) {
    com.shrct.businessprocess.product.RCIdentifiablePhysicalProductEntry rCIdentifiablePhysicalProductEntry = new com.shrct.businessprocess.product.impl.RCIdentifiablePhysicalProductEntryImpl(
    );
    objectFactory.create(rCIdentifiablePhysicalProductEntry);
    return rCIdentifiablePhysicalProductEntry;			
    
  }
  
  public static RCIdentifiablePhysicalProductEntry createRCIdentifiablePhysicalProductEntryImpl(final IObjectFactory objectFactory, final Procedure1<RCIdentifiablePhysicalProductEntry> init) {
    com.shrct.businessprocess.product.RCIdentifiablePhysicalProductEntry rCIdentifiablePhysicalProductEntry = new com.shrct.businessprocess.product.impl.RCIdentifiablePhysicalProductEntryImpl(
    );
    objectFactory.create(rCIdentifiablePhysicalProductEntry);
    init.apply(rCIdentifiablePhysicalProductEntry);
    
    return rCIdentifiablePhysicalProductEntry;			
    
  }
  
  public RCIdentifiablePhysicalProductEntryProxy toProxy() {
    com.shrct.businessprocess.product.proxy.RCIdentifiablePhysicalProductEntryProxy proxy = new com.shrct.businessprocess.product.proxy.RCIdentifiablePhysicalProductEntryProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    proxy.setStatus(this.getStatus().name());
    return proxy;
    
  }
}
